# -*- coding: UTF-8 -*-
"""
@Project ：swift-forge-engine
@File    ：model.py
@IDE     ：PyCharm 
@Author  ：Tony.Gan
@Date    ：2025/1/19 13:01 
@Des     ：
"""
from datetime import datetime
from typing import Annotated

from sqlalchemy import event, DateTime
from sqlalchemy.orm import DeclarativeBase, MappedAsDataclass, declared_attr, mapped_column, declarative_mixin, Session, \
    Mapped
import sqlalchemy as sa

from APP.utils.timezone import timezone

id_key = Annotated[
    int, mapped_column(primary_key=True, index=True, autoincrement=True, sort_order=-999, comment='主键id')
]


class MappedBase(DeclarativeBase):
    """
    是一个声明性基类，继承自 SQLAlchemy 的 DeclarativeBase。它为所有数据库模型类提供了默认的表名生成规则

    """

    @declared_attr.directive
    def __tablename__(cls) -> str:
        return cls.__name__.lower()


class DateTimeMixin(MappedAsDataclass):
    """日期时间 Mixin 数据类"""

    created_time: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), init=False, default_factory=timezone.now, sort_order=999, comment='创建时间'
    )
    updated_time: Mapped[datetime | None] = mapped_column(
        DateTime(timezone=True), init=False, onupdate=timezone.now,sort_order=999, comment='更新时间'
    )


class UserMixin(MappedAsDataclass):
    """用户 Mixin 数据类"""

    created_by: Mapped[int] = mapped_column(sort_order=998, comment='创建者')
    updated_by: Mapped[int | None] = mapped_column(init=False, default=None, sort_order=998, comment='修改者')


class DataClassBase(MappedAsDataclass, MappedBase):
    """
    声明性数据类基类, 它将带有数据类集成, 允许使用更高级配置

    """

    __abstract__ = True


class Base(DataClassBase):
    """
    DataClassBase 继承自 MappedAsDataclass 和 MappedBase，是一个带有数据类集成的声明性基类。
    MappedAsDataclass 使得类可以使用数据类的特性，如 __init__ 和 __repr__ 方法
    __abstract__ = True: 指定该类为抽象类，不会被直接映射为数据库表，而是作为其他模型类的基类。

    """

    __abstract__ = True


@declarative_mixin
class SoftDeleteMixin:
    is_del = mapped_column(sa.INTEGER(), default=0, comment='删除标识(0否 1是)')

    @classmethod
    def __declare_last__(cls):
        # 正确的事件注册方式 (SQLAlchemy 2.x)
        @event.listens_for(Session, "do_orm_execute")
        def _add_soft_delete_filter(execute_state):
            if (
                    execute_state.is_select
                    and not execute_state.is_column_load
                    and not execute_state.is_relationship_load
            ):
                entity = execute_state.bind_mapper.entity
                if issubclass(entity, cls):
                    execute_state.statement = execute_state.statement.where(
                        entity.is_del == 0
                    )